package com.dhl.commonutils.security;

import com.dhl.commonutils.jwt.JwtUtils;
import com.dhl.commonutils.utils.SpringUtils;
import com.dhl.config.SecurityConfig;
import com.dhl.entity.SysUser;
import com.dhl.service.SysUserService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;


/**
 * jwt认证管理器
 * @title: JwtAuthenticationFilter
 * @Author danghailiang
 * @Date: 2022/10/14 23:17
 * @Version 1.0
 */
@Slf4j
//@Component
public class JwtAuthenticationFilter extends BasicAuthenticationFilter  {
    /**
     * 用户服务
     */
    @Resource
    private SysUserService sysUserService;

    private SysUserService getSysUserByUsername(SysUserService sysUserService){
        if(Objects.isNull(sysUserService)){
            sysUserService = SpringUtils.getBean(SysUserService.class);
        }
        return sysUserService;
    }
    /**
     * 自定义登录用户服务
     */
    @Resource
    private MyUserUserDetailsServiceImpl myUserUserDetailsServiceImpl;

    private MyUserUserDetailsServiceImpl getMyUserUserDetailsServiceImpl(MyUserUserDetailsServiceImpl myUserUserDetailsServiceImpl){
        if(Objects.isNull(myUserUserDetailsServiceImpl)){
            myUserUserDetailsServiceImpl = SpringUtils.getBean(MyUserUserDetailsServiceImpl.class);
        }
        return myUserUserDetailsServiceImpl;
    }

    public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 获取token
        String token = request.getHeader("token");
        // 获取请求地址
        StringBuffer requestURL = request.getRequestURL();
//        log.info("Request URL: " + requestURL);
        // 如果token为空，或者url在白名单里，则放行
        if(StringUtils.isEmpty(token) || new ArrayList<String>(Arrays.asList(SecurityConfig.URL_WHITELIST)).contains(requestURL)){
            chain.doFilter(request,response);
            return;
        }
        boolean flag = JwtUtils.checkToken(token);
        if(!flag){
            throw new JwtException("用户未登录或登录已失效请重新登录");
        }

        Claims claims = JwtUtils.parseJWT(token);
        String username = (String) claims.get("username");
        SysUser sysUser = getSysUserByUsername(sysUserService).getSysUserByUsername(username);


        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(
                        username,
                        null,
                        // 获取权限列表
                        getMyUserUserDetailsServiceImpl(myUserUserDetailsServiceImpl)
                                .getUserAuthority(sysUser.getId())
                );
        // 放如security上下文中
        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        chain.doFilter(request,response);
    }
}
